//== SAGITTARIUS ============================================================================

//== FILEDOC =========================================================================

/** @file symtab.h
  * @brief Symbol table
  */

//== BEGINNING OF CODE ===============================================================

#ifndef __SAGUTTARUIS__SYMTAB__H_
#define __SAGUTTARUIS__SYMTAB__H_

//== INCLUDES ========================================================================

#include "sagittarius/core/SagittariusCore.h"
#include "sagittarius/lexer/lexcore.h"
#include "sagittarius/parallel/multisema.h"
//#include "sagittarius/symtab/set_uint64.h"
#include <stddef.h>

#define HASH_COLLISION 1
#define HASH_SUCCESS   0

#ifdef __cplusplus
extern "C" {
#endif

#if 0
typedef struct {
    /// Hash value for the symbol's name
    uint64 k;
    /** @brief Unique identifier
     * @details In the exptremely unlikely (with Murmur hash) event of
     * a collision, this serves to distinguish this symbol from others
     * that share the same hash value but have different names
     */
    uint64 u;
} symid;
#endif

/// Has two fields
//typedef uint64 symid;
typedef uint64 symcode;
typedef union {
    symcode k;
    uint8 u;
} symid;

typedef struct {
    symid id;
    LexBuf name;
} symtab_kvpair;

//hashkv_pair makehashkv_pair64_nth(void* p, size_t len);

typedef struct {
    uint32 n;
    uint32 depth;
    symtab_kvpair* e;
    //SG_DEF_MULTISEMA(sema);
} symtab_bucket;

typedef struct {
    /// Number of buckets
    uint64 nb;
    /// Buckets
    symtab_bucket* b;
    SG_DEF_MULTISEMA(sema);
} symtab;

/** @brief Gives the number of items with key @a k
 */
uint8 symtab_count_k(symtab* st, symid id, constLexBuf name);

typedef struct {
    /// The id, if found
    symid id;
    /// True if it already exists in the table
    int b;
} symcheck;

symcheck symtab_check(symtab* st, symid e);

LexBuf symtab_name(symtab* st, symid e);
LexBuf symtab_namek(symtab* st, symcode k);

int _symtab_insert(symtab* st, symtab_kvpair e);
symid symtab_get_or_insertl(symtab* st, constLexBuf name, size_t l);
symcode symtab_get_or_insert_cstr(symtab* st, char* buf);

symtab* symtab_rehash(symtab* st, uint32 nbuckets, uint32 depth);

//hashtable* create_hashtable(uint32 nbuckets, uint32 depth);

void finalize_symtab(symtab* st);

void symtab_dumpstate(int fd, symtab* h);

void symtabPrintSym(int fd, symtab*st, symid e);

void symtabPrintSymK(int fd, symtab*st, symcode k);

#ifdef __cplusplus
}//extern "C"
#endif

#endif
